package com.cooper.service.core;

import java.sql.Timestamp;
import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cooper.constants.CoralConstants;
import com.cooper.core.JsonResult;
import com.cooper.dao.core.UserDAO;
import com.cooper.dao.log.UserLoginDAO;
import com.cooper.entity.LogUserLogin;
import com.cooper.entity.UserInfo;
import com.cooper.pagination.PageInfo;
import com.cooper.pagination.PageResult;
import com.cooper.security.PasswordGeneration;
import com.cooper.security.RandomPassword;
import com.cooper.util.ThreadUtils;
import com.cooper.vo.UserSearchVo;
import com.google.common.base.Function;

@Service
public class UserService {
	
	protected Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private EmailExecutor emailExecutor;
	
	@Autowired
	private UserDAO userDao;
	
	@Autowired
	private UserLoginDAO userLoginDao;
	
	public Long addUser(UserInfo user) throws Exception{
		return this.userDao.addUser(user);
	}
	
	public UserInfo loadById(Long userId) {
		return this.userDao.loadById(userId);
	}
	
	public UserInfo getUser(String userName){
		return this.userDao.getUser(userName);
	}
	
	public int updateUser(UserInfo userInfo){
		return this.userDao.updateUser(userInfo);
	}
	
	public boolean updateUserFileId(Long userId, String userFileId) throws Exception{
		return this.userDao.updateUserFileId(userId, userFileId);
	}
	
	/**
	 * 验证用户密码
	 * @param user
	 * @return
	 * @throws Exception
	 */
	public UserInfo checkPassword(UserInfo user){
		if(null == user){
			return null;
		}
		return this.userDao.checkPassword(user);
	}
	
	/**
	 * 修改用户密码
	 * @param user userName userPassword modifier,gmtModified
	 * @return
	 */
	public boolean changePassword(UserInfo user){
		return this.userDao.changePassword(user);
	}
	
	/**
	 * 根据用户编码获取用户名称
	 * @param userId
	 * @return
	 * @throws Exception
	 * @date Nov 13, 2011 4:58:22 PM
	 * @author coraldane
	 */
	public String getUserName(long userId){
		UserInfo user = this.loadById(userId);
		if(null != user){
			return user.getUserName();
		}
		return null;
	}
	
	public boolean existsUserName(String userName){
		return this.userDao.existsUserName(userName) > 0;
	}
	
	public UserInfo existsUserEmail(String email){
		return this.userDao.existsUserEmail(email);
	}
	
	public void updateGroupId(Long userId, Long groupId){
		this.userDao.updateGroupId(userId, groupId);
	}
	
	public void updateEmail(Long userId, String email){
		this.userDao.updateEmail(userId, email);
	}
	
	@SuppressWarnings("unchecked")
	public PageResult<UserInfo> queryUserInfoList(PageInfo pageInfo, UserSearchVo searchVo){
		int rowCount = this.userDao.queryUserInfoCount(searchVo);
		pageInfo.setRowCount(rowCount);
		if(0 == rowCount){
			return new PageResult<UserInfo>(Collections.EMPTY_LIST, pageInfo);
		}
		List<UserInfo> dataList = this.userDao.queryUserInfoList(searchVo, pageInfo);
		return new PageResult<UserInfo>(dataList, pageInfo);
	}
	
	
	public boolean invalidUser(UserInfo userInfo){
		return this.userDao.invalidUser(userInfo) > 0;
	}
	
	public boolean restoreUser(UserInfo userInfo){
		return this.userDao.restoreUser(userInfo) > 0;
	}
	
	/**
	 * 验证用户信息  用户名 密码 email 等的验证,注意单个参数的传递
	 * @param searchVo
	 * @return
	 * @throws Exception
	 */
	public UserInfo checkUser(UserSearchVo searchVo){
		List<UserInfo> ret = this.userDao.queryUserInfoList(searchVo, new PageInfo());;
		if(null == ret || ret.size()==0 ){
			return null;
		}
		return ret.get(0);
	}
	
	public void logUserLogin(UserInfo userInfo, String clientIp, String sessionId) throws Exception{
		LogUserLogin loginLog = new LogUserLogin();
		BeanUtils.copyProperties(userInfo, loginLog);
		
		Timestamp now = new Timestamp(System.currentTimeMillis());
		loginLog.setUserId(userInfo.getId());
		loginLog.setLoginType("local");
		loginLog.setGmtLogin(now);
		loginLog.setClientIp(clientIp);
		loginLog.setSessionId(sessionId);
		
		ThreadUtils.newThread(loginLog, new Function<LogUserLogin, Long>(){
			@Override
			public Long apply(LogUserLogin input) {
				userDao.updateGmtLastLogin(input);
				userLoginDao.addUserLogin(input);
				return null;
			}
		});
	}
	
	/**
	 * 重置用户密码，发送新密码到用户邮件
	 * @param userInfo userName - required, comments - basePath
	 * @throws Exception
	 */
	public JsonResult resetPassword(String userName, String basePath) {
		JsonResult json = new JsonResult();
		
		try{
			UserSearchVo searchVo = new UserSearchVo();
			searchVo.setUserName(userName);
			UserInfo resetUser = checkUser(searchVo);
			if(resetUser==null){
				json.setMessage(userName+" not exists");
				json.setSuccess(false);
				return json;
			}
			
			String newPassword = new RandomPassword().doGenerate();
			resetUser.setUserPassword(PasswordGeneration.encrypt(newPassword));
			this.updateUser(resetUser);
			
			this.emailExecutor.init(CoralConstants.SENDMAIL_USER, CoralConstants.APP_NAME, CoralConstants.SENDMAIL_PASSWORD);
			String subject = CoralConstants.APP_NAME + " reset password mail";
			StringBuffer content = new StringBuffer();
			content.append("Your account [").append(userName)
				.append("]'s password on the site <a href='").append(basePath).append("' target='_blank'>").append(basePath)
				.append("</a> has been reset，the new password is：").append(newPassword)
				.append("<br/>And then you could change the password yourself。")
				.append("<br/>Be careful, please delete this email when you visited.<br/><br/>")
				.append("This mail has been sent automatic, don't reply!");
			
			String email = resetUser.getEmail();
			this.emailExecutor.send(email, subject, content.toString());
			json.setSuccess(true);
			json.setMessage("Password reset successful, plase visit your mail box!");
		} catch(Exception e){
			json.setMessage("reset password failure,{0}", e.getMessage());
			logger.error("send reset password mail error.", e);
		}
		return json;
	}
}

